feat(tbor): implement RSA mod exp - #586
Merged
Merged
Conversation
Vishal Soni (vsonims)
force-pushed
the
tbor/unwrap-key
branch
from
July 19, 2026 03:32
b3e53f6 to
427588b
Compare
Vishal Soni (vsonims)
force-pushed
the
tbor/rsa-crypto
branch
from
July 19, 2026 03:38
88d2fe7 to
57e66d9
Compare
Vishal Soni (vsonims)
force-pushed
the
tbor/unwrap-key
branch
from
July 20, 2026 19:23
427588b to
db29d52
Compare
Vishal Soni (vsonims)
force-pushed
the
tbor/rsa-crypto
branch
from
July 20, 2026 19:27
57e66d9 to
65359f9
Compare
Vishal Soni (vsonims)
force-pushed
the
tbor/unwrap-key
branch
from
July 20, 2026 19:34
db29d52 to
3655e3b
Compare
Vishal Soni (vsonims)
force-pushed
the
tbor/rsa-crypto
branch
from
July 20, 2026 19:35
65359f9 to
b68bd34
Compare
Vishal Soni (vsonims)
force-pushed
the
tbor/unwrap-key
branch
from
July 20, 2026 19:55
3655e3b to
2e032a4
Compare
Vishal Soni (vsonims)
force-pushed
the
tbor/rsa-crypto
branch
from
July 20, 2026 19:55
b68bd34 to
da96a6e
Compare
Vishal Soni (vsonims)
force-pushed
the
tbor/unwrap-key
branch
from
July 20, 2026 22:16
2e032a4 to
c4bd905
Compare
Add the TBOR RsaModExp command (opcode 0x1A): the RSA private-key primitive x = y^d mod n using a caller-held masked RSA private key (imported via UnwrapKey with the RSA / RSA-CRT key class). The device unmasks the key in place (recovering its modulus size and CRT form from the blob's key kind), checks the op's usage attribute (Decrypt -> decrypt, Sign -> sign), computes the modular exponentiation into the reserved response slot, and scrubs the recovered key on every path. The raw primitive underlying RSA decrypt / sign — the host applies and removes any padding. TBOR analogue of MBOR RsaModExp; there is no TBOR RSA key generation, so RSA keys enter only through UnwrapKey. Wire schemas (fw + host mirror) with a 1-byte RsaOp selector; dispatch / classifier / op.rs wiring; a strict from_pal::rsa_key mapping (rejects non-RSA-private kinds as InvalidKeyType). Emu tests cover host-verified RSA sign/decrypt roundtrips for 2K/3K/4K and 4K-CRT through the full UnwrapKey(Rsa) -> RsaModExp path, plus wrong-y-length and wrong-key-class rejects. Per-command docs added. Based on tbor/unwrap-key (#583), which provides the DMA-budget-efficient UnwrapKey that lets RSA-3072/4096 keys be imported within 8 KB. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0b09e50a-a9be-4bae-b347-d42dc775a258
Vishal Soni (vsonims)
force-pushed
the
tbor/rsa-crypto
branch
from
July 29, 2026 20:42
da96a6e to
6927433
Compare
Rajib Dutta (radutta99)
approved these changes
Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the TBOR
RsaModExpcommand (opcode0x1A) — the RSA private-key primitivex = y^d mod nusing a caller-held masked RSA private key (imported viaUnwrapKeywith the RSA / RSA-CRT key class). It is the raw primitive underlying RSA decrypt / sign; the host applies and removes any padding. There is no TBOR RSA key generation — RSA keys enter the device only throughUnwrapKey.0x1ARsaModExpy^d mod n→ reservedxslotDesign (mirrors the sibling TBOR crypto handlers)
decode_mutthe masked key in the request buffer (no scratch copy); recover modulus size / CRT form from the blob's key kind via a strictfrom_pal::rsa_key(non-RSA-private kinds →InvalidKeyType).RsaOp::Decryptrequires thedecryptattribute,RsaOp::Signrequiressign(checked post-unmask).yvalidated against the key's modulus length; result written straight into the reserved responsexslot.y/xare PKA-native wire little-endian; the device flips internally for OpenSSL.Changes
fw/core/lib/src/ddi/tbor/rsa_mod_exp.rs;from_pal::rsa_keymapping; dispatch + 3 classifiers inmod.rs;op.rsfrom_tbor_opcode.RsaOpselector +lib.rsregistration.UnwrapKey(Rsa) →RsaModExppath, plus wrong-y-length and wrong-key-class rejects.rsa_mod_exp.md+ README row.Testing
cargo checkfw core (host + Uno no_std) ✅Notes
tbor/unwrap-key), which was updated in this stack to makeUnwrapKeyDMA-budget-efficient (transient-vault masking, mirroring MBORRsaUnwrap) so RSA-3072/4096 (CRT + non-CRT) keys can be imported within the fixed per-IO 8 KB budget — the enabler for the RSA-4K roundtrip tests here. That fix (plus RSA-4K unwrap tests) lives in feat(tbor): implement RSA-AES key unwrap (GetUnwrappingKey + UnwrapKey) #583.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com